#!/usr/bin/env python
# encoding: utf-8
# Date: 2017/5/15 上午9:19
# file: demo1.py
# Email: wangjian2254@icloud.com
# Author: 王健
import json

from crane import StorageArea, StoragePosition, Crane, ActionCommand
from util.jsonresult import get_result

AREA = []
CRANE = []

BILLET = []
STEPS = []

ACTIONS = []

ALL_OBJECT = {'area': AREA, 'crane': CRANE, 'billet': BILLET, 'steps': STEPS, 'actions': ACTIONS}

def main():
    """
    测试
    :return:
    """

    # 构造 工厂环境

    # 库区3个
    area1 = StorageArea(u"1", u"1库区", 10 * (4000 + 1000), 300 * 1000, 2)

    area2 = StorageArea(u"2", u"2库区", 10 * (4000 + 1000), 300 * 1000, 2)

    area3 = StorageArea(u"3", u"3库区", 10 * (4000 + 1000), 300 * 1000, 2)

    area1.append_area(area2,
                      [(45000, 65000, 10000,), (41000, 65000, 10000,), (37000, 65000, 10000,),
                       (33000, 65000, 10000,), (29000, 65000, 10000,), (25000, 65000, 10000,),
                       (25000, 60000, 10000,), (29000, 60000, 10000,), (33000, 60000, 10000,),
                       (37000, 60000, 10000,), (41000, 60000, 10000,), (45000, 60000, 10000,)
                       ])
    area1.append_area(area3,
                      [(45000, 65000, 10000,), (41000, 65000, 10000,), (37000, 65000, 10000,),
                       (33000, 65000, 10000,), (29000, 65000, 10000,), (25000, 65000, 10000,),
                       (25000, 60000, 10000,), (29000, 60000, 10000,), (33000, 60000, 10000,),
                       (37000, 60000, 10000,), (41000, 60000, 10000,), (45000, 60000, 10000,)
                       ])

    area2.append_area(area1,
                      [
                          (5000, 60000, 10000,), (9000, 60000, 10000,),
                          (13000, 60000, 10000,),
                          (17000, 60000, 10000,), (21000, 60000, 10000,),
                          (25000, 60000, 10000,), (29000, 60000, 10000,), (33000, 60000, 10000,),
                          (37000, 60000, 10000,),
                          (41000, 60000, 10000,), (45000, 60000, 10000,),

                      ])
    area2.append_area(area3,
                      [(45000, 65000, 10000,), (41000, 65000, 10000,), (37000, 65000, 10000,),
                       (33000, 65000, 10000,), (29000, 65000, 10000,), (25000, 65000, 10000,),
                       (21000, 65000, 10000,), (17000, 65000, 10000,), (13000, 65000, 10000,),
                       (9000, 65000, 10000,), (5000, 65000, 10000,),

                       ])
    area3.append_area(area1,
                      [(5000, 60000, 10000,), (9000, 60000, 10000,), (13000, 60000, 10000,),
                       (17000, 60000, 10000,), (21000, 60000, 10000,), (21000, 65000, 10000,), (17000, 65000, 10000,),
                       (13000, 65000, 10000,), (9000, 65000, 10000,), (5000, 65000, 10000,), (1000, 65000, 10000,),
                       ])
    area3.append_area(area2,
                      [(5000, 60000, 10000,), (9000, 60000, 10000,), (13000, 60000, 10000,),
                       (17000, 60000, 10000,), (21000, 60000, 10000,), (21000, 65000, 10000,), (17000, 65000, 10000,),
                       (13000, 65000, 10000,), (9000, 65000, 10000,), (5000, 65000, 10000,), (1000, 65000, 10000,),
                       ])

    # 设置区域的出库区

    area1.append_external(StorageArea.YUANLIAO, [(20000, 320000, 20000), (35000, 320000, 20000)])
    area2.append_external(StorageArea.ZHONGJIAN, [(20000, 320000, 20000), (35000, 320000, 20000)])
    area2.append_external(StorageArea.JIANCHA, [(42000, 320000, 20000)])
    area3.append_external(StorageArea.CHENGPIN, [(20000, 320000, 20000), (35000, 320000, 20000)])

    AREA.append(area1)
    AREA.append(area2)
    AREA.append(area3)
    # 构造卡座
    for i in range(10):
        for k in range(60):

            if 13 <= k <= 18 and 5 <= i:
                pass
            else:
                p = StoragePosition(area1, u'%s-%s' % (i, k), 500 + i * 4000, 500 + (i + 1) * 4000,
                                    500 + k * 4000 + 4000 / 2.0, 4000)

                area1.append_position(i, k, p)

    for i in range(10):
        for k in range(60):
            if 13 <= k <= 18:
                pass
            else:
                p = StoragePosition(area2, u'%s-%s' % (i, k), 500 + i * 4000, 500 + (i + 1) * 4000,
                                    500 + k * 4000 + 4000 / 2.0, 4000)

                area2.append_position(i, k, p)

    for i in range(10):
        for k in range(60):
            if 13 <= k <= 18 and 5 > i:
                pass
            else:
                p = StoragePosition(area3, u'%s-%s' % (i, k), 500 + i * 4000, 500 + (i + 1) * 4000,
                                    500 + k * 4000 + 4000 / 2.0, 4000)

                area3.append_position(i, k, p)

    # 配置天车 一个库区配2个

    crane1a = Crane(1, area1)
    crane1a.set_position(1000, 3000, 3000)

    crane1b = Crane(2, area1)

    crane1b.set_position(1000, 200000, 3000)

    crane2a = Crane(3, area2)
    crane2a.set_position(1000, 3000, 3000)
    crane2b = Crane(4, area2)
    crane2b.set_position(1000, 200000, 3000)

    crane3a = Crane(5, area3)
    crane3a.set_position(1000, 3000, 3000)
    crane3b = Crane(6, area3)
    crane3b.set_position(1000, 200000, 3000)

    CRANE.append(crane1a)
    CRANE.append(crane1b)
    CRANE.append(crane2a)
    CRANE.append(crane2b)
    CRANE.append(crane3a)
    CRANE.append(crane3b)


def get_step_history():
    """
    获取所有历史步骤
    :return:
    """
    return json.dumps(STEPS)


def compute_step():
    """
    计算步骤状态
    :return:
    """

    step = {}

    return json.dumps(step)


def auto_10_same_billet(aim_area):
    """
    向区域添加10个相同型号的钢卷
    :param aim_area:
    :return:
    """


def auto_10_billet(aim_area):
    """
    向区域添加10个包含两个型号的钢卷
    :param aim_area:
    :return:
    """


def from_a_to_b(crane, s_area, s_pos, a_area, a_pos, command_id):
    """
    将钢坯从A移动到B
    :param crane:
    :param s_area:
    :param s_pos:
    :param aim_area:
    :param aim_pos:
    :return:
    """
    source_area = None
    for area in AREA:
        if area.name == s_area:
            source_area = area
            break

    aim_area = None
    for area in AREA:
        if area.name == a_area:
            aim_area = area
            break

    is_same_area = s_area == a_area
    source_pos = StoragePosition.make_position(s_pos)
    aim_pos = StoragePosition.make_position(a_pos)

    if is_same_area:
        # 不用跨区
        if source_area.center_y >= source_pos[1] and source_area.center_y >= aim_pos[1]:
            # 库区前部移动
            crane = source_area.local_cranes[0]
            if crane.is_free():
                # 库区前部的天车 空闲

                # 天车移动
                command_to_a_y = ActionCommand(command_id, Crane.ACTION_MOVE, source_pos)

                crane.add_actions(command_to_a_y)
                ACTIONS.append(command_to_a_y)

                # 小车移动
                command_to_a_x = ActionCommand(command_id, Crane.ACTION_MOVE_CAR, source_pos, True, command_to_a_y)

                crane.add_actions(command_to_a_x)
                ACTIONS.append(command_to_a_x)

                command_to_a_open = ActionCommand(command_id, Crane.ACTION_OPEN, None, True, command_to_a_x)

                crane.add_actions(command_to_a_open)
                ACTIONS.append(command_to_a_open)

                # 钩子移动
                command_to_a_z = ActionCommand(command_id, Crane.ACTION_MOVE_G, source_pos, True, command_to_a_open)

                crane.add_actions(command_to_a_z)
                ACTIONS.append(command_to_a_z)

                command_to_a_close = ActionCommand(command_id, Crane.ACTION_CLOSE, None, True, command_to_a_z)

                crane.add_actions(command_to_a_close)
                ACTIONS.append(command_to_a_close)

                # 钩子移动, 回到安全高度
                command_to_a_safe = ActionCommand(command_id, Crane.ACTION_MOVE_G, (source_pos[0], source_pos[1], 3000), True, command_to_a_close)

                crane.add_actions(command_to_a_safe)
                ACTIONS.append(command_to_a_safe)

                # 天车移动
                command_to_b_y = ActionCommand(command_id, Crane.ACTION_MOVE, aim_pos, True, command_to_a_safe)

                crane.add_actions(command_to_b_y)
                ACTIONS.append(command_to_b_y)

                # 小车移动
                command_to_b_x = ActionCommand(command_id, Crane.ACTION_MOVE_CAR, aim_pos, True, command_to_b_y)

                crane.add_actions(command_to_b_x)
                ACTIONS.append(command_to_b_x)

                # 钩子降落至失去重量
                command_to_b_z = ActionCommand(command_id, Crane.ACTION_DOWN_G, None, True, command_to_b_x)

                crane.add_actions(command_to_b_z)
                ACTIONS.append(command_to_b_z)

                command_to_b_open = ActionCommand(command_id, Crane.ACTION_OPEN, None, True, command_to_b_z)

                crane.add_actions(command_to_b_open)
                ACTIONS.append(command_to_b_open)

                # 钩子移动, 回到安全高度
                command_to_b_safe = ActionCommand(command_id, Crane.ACTION_MOVE_G, (aim_pos[0], aim_pos[1], 3000),
                                                  True, command_to_b_open)

                crane.add_actions(command_to_b_safe)
                ACTIONS.append(command_to_b_safe)

            else:
                # 库区前部的天车 繁忙
                pass
        elif source_area.center_y >= source_pos[1] and source_area.center_y < aim_pos[1]:
            # 库区前部往后移
            if source_area.local_cranes[0].is_free():
                # 库区前部的天车 空闲
                pass
            else:
                # 库区前部的天车 繁忙
                pass
        elif source_area.center_y < source_pos[1] and source_area.center_y >= aim_pos[1]:
            # 库区后部往前移
            if source_area.local_cranes[1].is_free():
                # 库区后部的天车 空闲
                pass
            else:
                # 库区后部的天车 繁忙
                pass
        elif source_area.center_y < source_pos[1] and source_area.center_y < aim_pos[1]:
            # 库区后部移动
            if source_area.local_cranes[1].is_free():
                # 库区后部的天车 空闲
                pass
            else:
                # 库区后部的天车 繁忙
                pass
        else:
            print u'Error(1001):  奇怪的移动方式'
    else:
        # 跨区
        if source_area.center_y >= source_pos[1]:
            # 库区前部,向其他库区移动
            pass
        elif source_area.center_y < source_pos[1]:
            # 库区后部,向其他库区移动
            pass
        else:
            print u'Error(1002):  奇怪的移动方式'

    free_crane = []
    for crane in s_area.local_cranes:
        if crane.is_free():
            free_crane.append(crane)


def from_a_move_to_b(crane, s_area, s_pos, aim_area, aim_pos):
    """
    从a吊起钢卷移动到b
    :param crane:
    :param s_area:
    :param s_pos:
    :param aim_area:
    :param aim_pos:
    :return:
    """


def to_b(crane, aim_pos):
    """
    天车从现在的位置移动到b
    :param crane:
    :param aim_pos:
    :return:
    """


def put_down(crane):
    """
    天车a放下钢卷
    :param crane:
    :return:
    """


def stop(crane):
    """
    天车a停车
    :param crane:
    :return:
    """


def on_message(client, userdata, msg):
    """
    监听消息
    :param client:
    :param userdata:
    :param msg:
    :return:
    """
    print msg.payload
    data = json.loads(msg.payload)

    route = data['route']
    payload = data['parms']

    result = None
    if route == 'from_a_to_b':
        result = from_a_to_b(payload['crane'], payload['source_area'], payload['source_pos'], payload['aim_area'],
                             payload['aim_pos'], payload['command_id'])

    elif route == 'to_b':
        result = to_b(payload['crane'], payload['aim_pos'])
    elif route == 'from_a_move_to_b':
        result = from_a_move_to_b(payload['crane'], payload['source_area'], payload['source_pos'], payload['aim_area'],
                                  payload['aim_pos'])
    elif route == 'put_down':
        result = put_down(payload['crane'])
    elif route == 'stop':
        result = stop(payload['crane'])

    elif route == 'auto_10_same_billet':
        result = auto_10_same_billet(payload['aim_area'])
    elif route == 'auto_10_billet':
        result = auto_10_billet(payload['aim_area'])

    elif route == 'refresh':
        result = None

    client.publish('web_api_response/%s' % data['callid'], get_result(True, u'', {'result': result, 'all_object': ALL_OBJECT}))


def mqtt():
    from mqtt.mqtt_client import mqtt_gateway_client_run

    mqtt_gateway_client_run('', on_message)


if __name__ == '__main__':
    import thread

    thread.start_new_thread(mqtt, ())
    main()

    try:
        import time

        while True:
            time.sleep(5)
    except:
        pass
